package com.baidu.bulls.stock.admin.user.service.impl;

import com.baidu.bulls.stock.admin.user.repository.AuthorityRoleMenuRepository;
import com.baidu.bulls.stock.admin.user.repository.AuthorityRoleOperationRepository;
import com.baidu.bulls.stock.admin.user.repository.AuthorityRoleRepository;
import com.baidu.bulls.stock.admin.user.repository.AuthorityUserRoleRepository;
import com.baidu.bulls.stock.admin.user.service.AuthorityLogicService;
import com.baidu.bulls.stock.common.exception.BusinessException;
import com.baidu.bulls.stock.common.exception.constants.ApplicationErrorCodeEnum;
import com.baidu.bulls.stock.entity.user.*;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Service
@Log4j2
public class AuthorityLogicServiceImpl implements AuthorityLogicService {

    private static final String MENU_FLAG = "M_";
    private static final String MENU_OPT_FLAG = "O_";

    @Autowired
    private AuthorityRoleRepository authorityRoleRepository;
    @Autowired
    private AuthorityRoleMenuRepository authorityRoleMenuRepository;
    @Autowired
    private AuthorityRoleOperationRepository authorityRoleOperationRepository;
    @Autowired
    private AuthorityUserRoleRepository authorityUserRoleRepository;


    /**
     * 保存角色权限接口
     * roleAuth:
     * roleIds:
     *
     * @throws Exception
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void savePrivileges(String roleAuth, String... roleIds) throws BusinessException {
        log.info("Process in AuthorityLogicServiceImpl.savaPrivileges method. para,roleAuth:{},roleIds:{}", roleAuth, roleIds);
        //1.保存多个角色的权限信息，支持批量处理 方式，参数前端校验
        for (String roleId : roleIds) {
            //2.将roleid 进行校验，查看是否存在
            Long roleIdLong = Long.valueOf(roleId);
            privilegedRole(roleIdLong);
            //3. 保存角色和权限的关系
            saveRolePrivileges(roleAuth, roleIdLong);
        }


    }

    //对角色是否存在进行校验
    private AuthorityRole privilegedRole(Long roleIdLong) throws BusinessException {
        Optional<AuthorityRole> role = authorityRoleRepository.findById(roleIdLong);
        //如果roleid不存在，那么抛出异常
        if (!role.isPresent()) {
            throw new BusinessException(ApplicationErrorCodeEnum.USER_NOT_FOUND);
        }
        return role.get();
    }

    /**
     * 保存角色和权限的关系
     */
    private void saveRolePrivileges(String roleAuth, Long roleId) {
        log.info("Process in  saveRolePrivileges method,param,roleAuth:{},roleIds:{}", roleAuth, roleId);
        //过滤roleAuth参数数据，规范“M_id, O_id” m开头为菜单，o开头为菜单操作,清楚垃圾数据
        String[] roles = roleAuth.replace("-1", "").trim().split(",");
        //对权限做一个去重
        List<String> roleList = Stream.of(roles).distinct().collect(Collectors.toList());
        //保存之前先删除原有的菜单和菜单操作
        authorityRoleMenuRepository.deleteAllByRoleId(roleId);
        authorityRoleOperationRepository.deleteAllByRoleId(roleId);
        AuthorityRoleMenu authorityRoleMenu;
        AuthorityRoleOperation authorityRoleOperation;

        //重新进行保存,id是菜单id或者菜单操作id
        for (String id : roleList) {
            if (id.contains(MENU_FLAG)) {
                authorityRoleMenu = new AuthorityRoleMenu(roleId, Long.parseLong(id.replace(MENU_FLAG, "").trim()));
                authorityRoleMenuRepository.save(authorityRoleMenu);
            } else if (id.contains(MENU_OPT_FLAG)) {
                authorityRoleOperation = new AuthorityRoleOperation(roleId, Long.parseLong(id.replace(MENU_OPT_FLAG, "").trim()));
                authorityRoleOperationRepository.save(authorityRoleOperation);
            } else {
                log.warn("unknown menu or opt ! id{}", id);
            }
        }
    }

    /**
     * 分配用户与角色的关联关系接口
     *
     * @param authorityUserRole
     * @param authorityUser
     * @throws BusinessException
     */
    @Override
    @Transactional
    public void userAddRoles(AuthorityUserRole authorityUserRole, AuthorityUser authorityUser) throws BusinessException {
        log.info("Process in userAddRoles method,param authorityUserRole:{}", authorityUserRole);
        //先查找改用户关联的角色有多少
        List<AuthorityUserRole> allByUserId = authorityUserRoleRepository.findAllByUserId(authorityUserRole.getUserId());

        //查该角色的相应信息
        AuthorityRole authorityRole = privilegedRole(authorityUserRole.getRoleId());

       if (!CollectionUtils.isEmpty(allByUserId)){
           //该用户有咩存在在多个同机构下的角色
           for (AuthorityUserRole userRole : allByUserId) {
               if (authorityRole.getInstitutionTypeId().equals(userRole.getInstitutionTypeId())) {
                   throw new BusinessException(ApplicationErrorCodeEnum.USER_ROLE_REPETITION);
               }
           }
       }

        //完善信息
        authorityUserRole.setRoleName(authorityRole.getRoleName());
        authorityUserRole.setCreateTime(LocalDateTime.now());
        authorityUserRole.setInstitutionId(authorityRole.getInstitutionId());
        authorityUserRole.setInstitutionTypeId(authorityRole.getInstitutionTypeId());
        authorityUserRole.setCreateBy(authorityUser.getId());
        authorityUserRole.setCreateUser(authorityUser.getUserName());
        authorityUserRole.setLastUpdateBy(authorityUser.getId());
        authorityUserRole.setLastUpdateTime(LocalDateTime.now());
        authorityUserRole.setLastUpdateUser(authorityUser.getUserName());

        //添加用户与角色的关系
        authorityUserRoleRepository.save(authorityUserRole);
    }


}
